﻿using System.ComponentModel;
using System.Runtime.InteropServices;
using System.Web.UI.WebControls.WebParts;
using Trentacular.Office.Server.Search.FacetedSearch;
using Trentacular.Office.Server.Search.FacetedSearch.Providers;
using Trentacular.SharePoint.Web.UI.WebParts;

namespace Trentacular.Office.Server.Web.UI.WebParts
{
    /// <summary>
    /// Web Part that displays contextual facets and enables refinement of the search
    /// results.
    /// </summary>
    [Guid("789A74C5-297F-4986-9939-CE55575B8533")]
    [EditorPart(
        "FacetedSearchEditor",
        "Faceted Search Configuration",
        "~/_controltemplates/trentacular/FacetedSearchEditor.ascx"
        )]
    public class FacetedSearchWebPart : UserControlWebPart
	{
        /// <summary>
        /// Initializes a new instance of the <see cref="FacetedSearchWebPart"/> class.
        /// </summary>
        public FacetedSearchWebPart()
            : base("~/_controltemplates/trentacular/SearchFacets.ascx")
        {
            this.AllowEdit = false;
            this.FacetResultsRowLimit = 500;
        }

        /// <summary>
        /// Number of results returned by the search engine in one resultset.
        /// The higher value, the more accurate is the calculation of facet hits.
        /// </summary>
        /// <remarks>High value will result in performance penalty.</remarks>
        [DefaultValue(500)]
        [Personalizable(PersonalizationScope.Shared)]
        public int FacetResultsRowLimit { get; set; }

        /// <summary>
        /// Gets or sets a value indicating whether to display the debugging panel.
        /// </summary>
        /// <value><c>true</c> if the debugging panel is to be displayed;
        /// otherwise, <c>false</c>.</value>
        [DefaultValue(false)]
        [Personalizable(PersonalizationScope.Shared)]
        public bool EnableDebugPanel { get; set; }

        private FacetProviderConfigurationCollection _facetProviderConfigurations;

        /// <summary>
        /// Gets or sets the facet provider configurations.
        /// </summary>
        /// <value>The facet provider configurations.</value>
        [Personalizable(PersonalizationScope.Shared)]
        public FacetProviderConfigurationCollection FacetProviderConfigurations
        {
            get
            {
                if (_facetProviderConfigurations == null)
                    _facetProviderConfigurations = GetDefaultConfiguration();
                return _facetProviderConfigurations;
            }
            set
            {
                _facetProviderConfigurations = value;
            }
        }

        private FacetProviderConfigurationCollection GetDefaultConfiguration()
        {
            return new FacetProviderConfigurationCollection
            {
                CreateFacetProviderConfiguration("Author", "Author"),
                CreateDateTimeFacetProviderConfiguration(
                    "Last Modified",
                    "Write",
                    "MMMM yyyy"
                    ),
                new FacetProviderConfiguration
                {
                    DisplayName = "Document Type",
                    FacetProviderTypeName =
                        typeof(DocumentTypeFacetProvider).AssemblyQualifiedName,
                    Properties = new ConfigurationPropertyCollection
                    {
                        new ConfigurationProperty
                        {
                            Key = "f1_DisplayName",
                            Value = "All Documents"
                        },
                        new ConfigurationProperty
                        {
                            Key = "f1_IconPath",
                            Value = "/_layouts/images/trentacular/dt-file.png"
                        },
                        new ConfigurationProperty
                        {
                            Key = "f2_DisplayName",
                            Value = "Word Documents"
                        },
                        new ConfigurationProperty
                        {
                            Key = "f2_FileExtensions",
                            Value = "doc,docx,dot"
                        },
                        new ConfigurationProperty
                        {
                            Key = "f2_IconPath",
                            Value = "/_layouts/images/trentacular/dt-word.png"
                        },
                        new ConfigurationProperty
                        {
                            Key = "f3_DisplayName",
                            Value = "Excel Documents"
                        },
                        new ConfigurationProperty
                        {
                            Key = "f3_FileExtensions",
                            Value = "xls,xlsx,xlt"
                        },
                        new ConfigurationProperty
                        {
                            Key = "f3_IconPath",
                            Value = "/_layouts/images/trentacular/dt-excel.png" },
                        new ConfigurationProperty
                        {
                            Key = "f4_DisplayName",
                            Value = "PowerPoint Documents"
                        },
                        new ConfigurationProperty
                        {
                            Key = "f4_FileExtensions",
                            Value = "ppt,pptx"
                        },
                        new ConfigurationProperty
                        {
                            Key = "f4_IconPath",
                            Value = "/_layouts/images/trentacular/dt-powerpoint.png" },
                        new ConfigurationProperty
                        {
                            Key = "f5_DisplayName",
                            Value = "PDF Documents"
                        },
                        new ConfigurationProperty
                        {
                            Key = "f5_FileExtensions",
                            Value = "pdf"
                        },
                        new ConfigurationProperty
                        {
                            Key = "f5_IconPath",
                            Value = "/_layouts/images/trentacular/dt-pdf.png"
                        }
                    }
                },
                CreateManagedPropertyConfiguration(
                    "Content Type",
                    "ContentType",
                    "^(text/|application/|Folder$)"
                    ),
                new FacetProviderConfiguration
                {
                    DisplayName = "Site",
                    FacetProviderTypeName =
                        typeof(SiteFacetProvider).AssemblyQualifiedName
                }
            };
        }

        private FacetProviderConfiguration CreateManagedPropertyConfiguration(
            string displayName,
            string managedPropertyName,
            string exclusionExpression
            )
        {
            var facetProviderConfiguration =
                            CreateFacetProviderConfiguration(
                                displayName,
                                managedPropertyName
                                );

            facetProviderConfiguration
                .Properties[ManagedPropertyFacetProvider.ExclusionExpressionKey] =
                exclusionExpression;
            
            return facetProviderConfiguration;
        }

        private FacetProviderConfiguration CreateDateTimeFacetProviderConfiguration(
            string displayName,
            string managedPropertyName,
            string monthDisplayDateFormat
            )
        {
            var facetProviderConfiguration =
                            CreateFacetProviderConfiguration(
                                displayName,
                                managedPropertyName
                                );

            facetProviderConfiguration.Properties[
                DateTimeManagedPropertyFacetBuilder.MonthDisplayDateFormatKey
                ] = monthDisplayDateFormat;

            return facetProviderConfiguration;
        }

        private FacetProviderConfiguration CreateFacetProviderConfiguration(
            string displayName,
            string managedPropertyName
            )
        {
            return new FacetProviderConfiguration
            {
                DisplayName = displayName,
                FacetProviderTypeName =
                    typeof(ManagedPropertyFacetProvider).AssemblyQualifiedName,
                Properties = new ConfigurationPropertyCollection
                {
                    new ConfigurationProperty
                    {
                        Key = ManagedPropertyFacetProvider.ManagedPropertyNameKey,
                        Value = managedPropertyName
                    }
                }
            };
        }
	}
}
